using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Collections;

namespace CodePlex.SpaceBlock.UI.Controls
{
    public partial class BufferedTextBoxControl : BaseControl
    {

        private int _maxBufferSize;
        private bool _dirty;
        private StringBuilder _builder;
        private readonly object _builderLock = new object();
        private readonly object _boxLock = new object();


        public BufferedTextBoxControl()
        {
            InitializeComponent();


            _maxBufferSize = 20000;

            this.DoubleBuffered = true;


            this.Clear();
         
            Timer t = new Timer();
            t.Interval = 100;

            t.Tick += delegate
            {
                if (!this.Visible)
                {
                    return;
                }

                lock (_boxLock)
                {
                    if (_dirty)
                    {
                        _dirty = false;

                        string text = _builder.ToString();

                        int i = text.IndexOfAny(new char[] { '\r','\n'});

                        if (i > -1)
                        {
                            text = text.Substring(i);
                        }
                        text = text + "\r\n";


                        _box.Text = text;
                        _box.Select(text.Length, 0);
                        _box.ScrollToCaret();

                    }
                }
            };

            t.Start();
        }


        public bool WordWrap
        {
            get
            {
                return _box.WordWrap;
            }
            set
            {
                _box.WordWrap = value;
            }
        }

        public void WriteLine(string value)
        {
            lock (_builderLock)
            {
                _builder.AppendLine(value);
                this.UpdateBuilder();
            }

        }

        public void Write(string value)
        {
            lock (_builderLock)
            {
                _builder.Append(value);
                this.UpdateBuilder();
            }
            
        }


        public void Clear()
        {
            lock (_builderLock)
            {
                _builder = new StringBuilder(_maxBufferSize);
                this.UpdateBuilder();
            }
        }

        private void UpdateBuilder()
        {
            _dirty = true;

            if (_builder.Length > _maxBufferSize)
            {
                _builder.Remove(0, _builder.Length - _maxBufferSize);
            }
        }



    }
}
